<?php

namespace App\Models;

use App\Http\Controllers\Admin\CommonController;
use App\Http\Controllers\SmallPayV3;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

/*活动排名model*/

class AnswerActivityRanking extends BaseModel
{


    /**
     * 获取活动排名
     * @param act_id int 活动id
     * @param unit_id int 单位id  除独立活动外，若传了则是单位排名，不传则是总排名  ；独立活动，单位排名等于独立排名
     * @param page int 页码
     * @param limit int 分页大小
     * 
     * 排序规则：先以答题数排序，答题数相同，在以正确率排序，正确率相应，在以时长排序，时长相同，在以时间排序  
     */
    public function getRanking($pattern, $act_id, $unit_id, $limit = 10)
    {
        $activityModel = new AnswerActivity();
        $model = $activityModel->getAnswerTotalRecordModel($pattern);

        $unit_id = $unit_id ?: 0;
        $res = $model->from($model->getTable() . ' as p')->select(
            'p.id',
            'p.user_guid',
            'p.act_id',
            'p.unit_id',
            'p.answer_number',
            'p.correct_number',
            'p.accuracy',
            'p.times',
            'p.create_time',
            'p.change_time',
            'p.price',
            'p.pay_time',
            'p.order_id',
            'p.state',
            'p.fail_reason'
        )
            ->join('user_info as u', 'u.token', '=', 'p.user_guid')
            ->where('p.act_id', $act_id)
            ->where('p.unit_id', $unit_id)
            ->orderByDesc('p.correct_number')
            ->orderByDesc('p.accuracy')
            ->orderBy('p.times') // 答题时长
            ->orderBy('p.change_time')
            ->paginate($limit)
            ->toArray();

        foreach ($res['data'] as $key => $val) {
            $res['data'][$key]['price'] = $val['state'] ? $val['price'] : null;
        }

        return $res;
    }

    /**
     * 查询指定用户排名
     * @param  $name
     */
    public function userRanking($pattern, $act_id, $unit_id, $user_guid)
    {
        $activityModel = new AnswerActivity();
        $model = $activityModel->getAnswerTotalRecordModel($pattern);
        $unit_id = $unit_id ?: 0;

        $user_record = $model->from($model->getTable() . ' as p')
            ->select(
                'p.id',
                'p.user_guid',
                'p.act_id',
                'p.unit_id',
                'p.answer_number',
                'p.correct_number',
                'p.accuracy',
                'p.times',
                'p.create_time',
                'p.change_time',
                'p.price',
                'p.pay_time',
                'p.order_id',
                'p.state',
                'p.fail_reason'
            )
            ->join('user_info as u', 'u.token', '=', 'p.user_guid')
            ->where('p.act_id', $act_id)
            ->where('p.unit_id', $unit_id)
            ->where('p.user_guid', $user_guid)
            ->first();

        if (empty($user_record)) {
            return [
                'id' => 0,
                'rank' => 0,
                'user_guid' => null,
                'act_id' => null,
                'unit_id' => null,
                'correct_number' => 0,
                'accuracy' => 0,
                'times' => 0,
                'create_time' => null,
                'change_time' => null,
                'price' => null,
                'pay_time' => null,
                'order_id' => null,
                'state' => null,
                'fail_reason' => null,
            ];
        }

        // $concat_field = $user_record['correct_number'] . '-' . $user_record['accuracy'] . '-' . $user_record['change_time'];
        //获取所有排名
        $rank = $model->from($model->getTable() . ' as p')
            ->select('p.id', 'p.user_guid')
            ->join('user_info as u', 'u.token', '=', 'p.user_guid')
            ->where('p.act_id', $act_id)
            ->where('p.unit_id', $unit_id)
            // ->where(DB::raw("CONCAT_WS('-',correct_number,accuracy,change_time)"),  '>',  $concat_field)
            ->orderByDesc('p.correct_number')
            ->orderByDesc('p.accuracy')
            ->orderBy('p.times') // 答题时长
            ->orderBy('p.change_time')
            ->get();

        $self_rank = 0;
        foreach ($rank as $key => $val) {
            if ($val['user_guid'] != $user_guid) {
                continue;
            }
            $self_rank = $key + 1;
            break;
        }

        $user_record = $user_record->toArray();
        return [
            'id' => $user_record['id'],
            'rank' => $self_rank,
            'user_guid' => $user_record['user_guid'],
            'act_id' => $user_record['act_id'],
            'unit_id' => $user_record['unit_id'],
            'correct_number' => $user_record['correct_number'],
            'accuracy' => $user_record['accuracy'],
            'times' => second_to_time($user_record['times']),
            'create_time' => $user_record['create_time'],
            'change_time' => $user_record['change_time'],
            'price' => $user_record['state'] ? $user_record['price'] : null,
            'pay_time' => $user_record['pay_time'],
            'order_id' => $user_record['order_id'],
            'state' => $user_record['state'],
            'fail_reason' => $user_record['fail_reason'],
        ];
    }


    /**
     * 排名转账
     * @param content  json格式数据 
     *                              * @param id 排名列表数据id
     *                              * @param rank 排名数字
     *                              * @param act_id 活动id
     *                              * @param user_guid 用户id 
     *                              * @param price 转账金额  单位 元  0.3~200 之间的数字
     */
    public function rankingTransfer($content)
    {
        $content = json_decode($content, true);
        if (empty($content)) {
            return '转账失败';
        }
        if (count($content) > 30) {
            return '一次性转账不能超过30个用户';
        }
        //先验证数据，验证完后在进行转账
        $act_id = null;
        foreach ($content as $key => $val) {
            if (empty($val['id']) || empty($val['rank']) || empty($val['act_id']) || empty($val['user_guid']) || strlen($val['user_guid']) != 32 || empty($val['price']) || !is_numeric($val['price'])) {
                return '数据格式有误，请检查';
            }
            if ($val['price'] < 0.3 || $val['price'] > 200) {
                return '转账金额必须在 0.3~200 元之间';
            }
            if (empty($act_id)) {
                $act_id = $val['act_id'];
            }
            if ($act_id != $val['act_id']) {
                return '批量转账一次只支持一个活动的数据，请重新选择';
            }
        }
        if (empty($act_id)) {
            return '当前活动不存在';
        }
        $activityModel = new AnswerActivity();
        $act_info = $activityModel->detail($act_id, ['id', 'title', 'node', 'prize_form', 'answer_end_time', 'start_time', 'end_time', 'pattern']);
        if (empty($act_info)) {
            return '当前活动不存在或已被删除';
        }
        if ($act_info['answer_end_time'] > date('Y-m-d H:i:s')) {
            return '当前答题未结束，不允许转账';
        }
        if (date('Y-m-d H:i:s', strtotime('+30 day', strtotime($act_info['end_time']))) < date('Y-m-d H:i:s')) {
            return '当前活动已结束很久，不允许转账';
        }
        if ($act_info['prize_form'] != 1) {
            return '当前活动类型，不允许转账';
        }

        //排名转账只支持排名模式，其他模式不支持转账
        $model = $activityModel->getAnswerTotalRecordModel($act_info['pattern']);
        //进行转账前操作
        $return_data = [];
        $commonControllerObj = new CommonController();
        foreach ($content as $key => $val) {
            $return_data[$key][$commonControllerObj->list_index_key] = $key + 1;
            $return_data[$key]['rank'] = $val['rank'];
            $return_data[$key]['price'] = $val['price'];
            $return_data[$key]['fail_reason'] = null;

            $userInfoModel = new UserInfo();
            $wechat_user_info = $userInfoModel->getWechatInfo($val['user_guid']);

            if (empty($wechat_user_info) || empty($wechat_user_info['open_id'])) {
                Log::error("用户获取失败,不能转账：" . $val['user_guid']);

                $return_data[$key]['nickname'] = null;
                $return_data[$key]['state'] = 2; //失败
                $return_data[$key]['fail_reason'] = '用户信息获取失败,不能转账';
                continue;
            }
            //微信昵称
            $return_data[$key]['nickname'] = $wechat_user_info['nickname'];
            $transfer_info = $model->where('id', $val['id'])->where('act_id', $val['act_id'])->where('user_guid', $val['user_guid'])->first();
            if (empty($transfer_info)) {
                $return_data[$key]['state'] = 2; //失败
                $return_data[$key]['fail_reason'] = '排名信息获取失败,不能转账';
                continue;
            }
            if ($transfer_info['state'] == 1 || $transfer_info['state'] == 3) {
                $return_data[$key]['state'] = 2; //失败
                $return_data[$key]['fail_reason'] = '当前用户红包已发放或在发放中，请勿重复操作';
                continue;
            }
            //进行转账操作，写入正在转账中
            $order_id = !empty($transfer_info['order_id']) ? $transfer_info['order_id'] : get_order_id(); //如果之前转账失败，存在订单号，就用之前的订单号
            $model->where('id', $val['id'])->update(['pay_time' => date('Y-m-d H:i:s'), 'state' => 3, 'price' => $val['price'], 'order_id' => $order_id]);

            $price = $val['price'] * 100; //微信转账以分为单位
            $packet_msg = "【" . $act_info['title'] . "】竞答活动,排名红包";
            $smallPayModel = new SmallPayV3();

            $res = $smallPayModel->wechatTransfer($order_id, $price, $wechat_user_info['open_id'], '竞答活动,排名红包', $packet_msg);
            if ($res !== true) {
                Log::error("转账失败,理由为" . $res . ",用户guid：" . $val['user_guid']);

                $model->where('id', $val['id'])->update(['pay_time' => date('Y-m-d H:i:s'), 'state' => 2, 'fail_reason' => $res]);
                $return_data[$key]['state'] = 2; //失败
                $return_data[$key]['fail_reason'] = $res;
            } else {
                $return_data[$key]['state'] = 3; //转账中
                $return_data[$key]['fail_reason'] = ''; //结果稍后查询
            }
        }
        return $return_data;
    }

    /**
     * 查看执行结果
     */
    public function getExecuteResult($pattern, $act_id)
    {
        //限制用户多次点击
        $key = md5('get_answer_activity_execute_result_rank' . $act_id);
        $oldKey =  Cache::get($key); //没有缓存返回false
        if ($oldKey) {
            return false; //不执行
        } else {
            Cache::put($key, 1, 60); //1分钟只能执行一次
        }

        $activityModel = new AnswerActivity();
        $model = $activityModel->getAnswerTotalRecordModel($pattern);

        $res = $model->select('id', 'user_guid', 'act_id', 'price', 'pay_time', 'order_id', 'state', 'fail_reason')
            ->where('act_id', $act_id)
            ->where('state', 3)
            ->where('pay_time', '>', date('Y-m-d H:i:s', strtotime('-30 day'))) //执行很久的转账不在查询
            ->get()
            ->toArray();
        if (empty($res)) {
            return false;
        }

        $smallPayModel = new SmallPayV3();
        $packet_transfer_model = new AnswerActivityPacketTransfer();
        foreach ($res as $key => $val) {
            $result = $smallPayModel->getExecuteResult($val['order_id']);
            //写入转账日志
            if ($result) {
                if (empty($result['out_detail_no'])) {
                    $result['out_detail_no'] = $val['order_id'];
                    $result['out_batch_no'] = $val['order_id'] . '1';
                }
                $result['pattern'] = $pattern;
                $result['create_time'] = date('Y-m-d H:i:s'); //执行时间
                $packet_transfer_model->insert($result);
            } else {
                Log::error("未查询到商家转账到企业执行结果，请查询,用户guid：" . $val['user_guid'] . ';订单号：' . $val['order_id']);
                continue;
            }

            if (isset($result['code']) && $result['code'] == 'INVALID_REQUEST') {
                //还在等待执行，不处理
                continue;
            }

            if (isset($result['code']) && $result['code'] == 'NOT_FOUND') {
                $model->where('id', $val['id'])->update(['pay_time' => date('Y-m-d H:i:s'), 'state' => 2, 'fail_reason' => $result['message']]);
                continue;
            }

            //转账失败
            if (isset($result['detail_status']) && $result['detail_status'] == 'FAIL') {
                $fail_reason = $result['fail_reason'] ? $result['fail_reason'] : '';
                if ($fail_reason == 'MERCHANT_REJECT') {
                    $fail_reason = '商户拒绝转账';
                } else {
                    $fail_reason = $fail_reason . ' 具体原因请到微信支付商户平台后台查询';
                }
                $model->where('id', $val['id'])->update(['pay_time' => $result['update_time'], 'state' => 2, 'fail_reason' => $fail_reason]);
                continue;
            }


            if (isset($result['detail_status']) && $result['detail_status'] == 'SUCCESS') {
                $model->where('id', $val['id'])->update(['pay_time' => $result['update_time'], 'state' => 1, 'fail_reason' => null]);
                continue;
            }

            Log::error("未解析情况，记录ID" . $val['id'] . "订单号：" . $val['order_id']);
            Log::error($result);
        }
    }
}
